home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / COMMS / C101.ZIP / UUPC11XS.ZIP / UUCICO / ULIBNT.C < prev    next >
C/C++ Source or Header  |  1992-11-12  |  36KB  |  1,070 lines

  1. /*
  2.    ibmpc/ulibnt.c
  3.  
  4.    DCP Windows/NT system-dependent library
  5.  
  6.    Services provided by ulib.c:
  7.  
  8.    - UNIX commands simulation
  9.    - serial I/O
  10.    - set console mode to what's appropriate for UUPC/extended input
  11.  
  12.    Updated:
  13.  
  14.       14May89  - Added hangup() procedure                               ahd
  15.       21Jan90  - Replaced code for rnews() from Wolfgang Tremmel
  16.                  <tremmel@garf.ira.uka.de> to correct failure to
  17.                  properly read compressed news.                         ahd
  18.    6  Sep 90   - Change logging of line data to printable               ahd
  19.       8 Sep 90 - Split ulib.c into dcplib.c and ulib.c                  ahd
  20.       6 Apr 90 - Create libary for OS/2 from ulib.c                     ahd
  21.       Apr 92   - Ported to NT, split off from ulibos2.c                 dmw
  22.       20 Oct 92- added setstdinmode() to set input mode                 dmw
  23. */
  24.  
  25. /*--------------------------------------------------------------------*/
  26. /*                        System include files                        */
  27. /*--------------------------------------------------------------------*/
  28.  
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <fcntl.h>
  33. #include <io.h>
  34. #include <time.h>
  35.  
  36. /*--------------------------------------------------------------------*/
  37. /*                         OS/2/Windows NT include files              */
  38. /*--------------------------------------------------------------------*/
  39.  
  40. #ifdef WIN32
  41. #include <windows.h>
  42. #else
  43. #define INCL_BASE
  44. #include <os2.h>
  45. #endif
  46. /*--------------------------------------------------------------------*/
  47. /*                    UUPC/extended include files                     */
  48. /*--------------------------------------------------------------------*/
  49.  
  50. #include "lib.h"
  51. #include "ulib.h"
  52. #include "ssleep.h"
  53.  
  54. #include <limits.h>
  55.  
  56. currentfile();
  57.  
  58. boolean   port_active = FALSE;  /* TRUE = port handler handler active  */
  59. static boolean   carrierdetect = FALSE;  /* Modem is not connected     */
  60.  
  61. #define LINELOG "LineData.Log"      /* log serial line data here */
  62.  
  63. static int log_handle;
  64. static int logmode = 0;             /* Not yet logging            */
  65. #define WRITING 1
  66. #define READING 2
  67. static FILE *log_stream;
  68. static boolean hangup_needed = FALSE;
  69. static boolean console = FALSE;
  70.  
  71. static current_baud = 0;
  72.  
  73. #define FAR_NULL ((PVOID) 0L)
  74.  
  75. /*--------------------------------------------------------------------*/
  76. /*           Definitions of control structures for DOS API            */
  77. /*--------------------------------------------------------------------*/
  78.  
  79. #ifdef WIN32
  80. static HANDLE hCom;
  81. static DCB dcb;
  82. #else
  83. #endif
  84. /*--------------------------------------------------------------------*/
  85. /*    o p e n l i n e                                                 */
  86. /*                                                                    */
  87. /*    Open the serial port for I/O                                    */
  88. /*--------------------------------------------------------------------*/
  89.  
  90. int openline(char *name, BPS baud, const boolean direct )
  91. {
  92.    int value;
  93.  
  94. #ifdef WIN32
  95.    DWORD dwError;
  96.    DWORD Error;
  97.    BOOL rc;
  98.    HANDLE hProcess;
  99. #else
  100. #endif
  101.    if (port_active)              /* Was the port already active?     ahd   */
  102.       closeline();               /* Yes --> Shutdown it before open  ahd   */
  103.    if ( port_active )
  104.       panic();
  105.  
  106.    printmsg(15, "openline: %s, %d", name, baud);
  107.  
  108.    if (!equal(name,"CON") && sscanf(name, "COM%d", &value) != 1)
  109.    {
  110.       printmsg(0,"openline: Communications port must be format COMx, was %s",
  111.          name);
  112.       panic();
  113.    }
  114.  
  115. #ifdef WIN32
  116.    hCom = CreateFile( name,
  117.         GENERIC_READ | GENERIC_WRITE,
  118.         0,
  119.         NULL,
  120.         OPEN_EXISTING,
  121.         0,
  122.         NULL);
  123.  
  124.    if (hCom == (HANDLE) 0xFFFFFFFF) {
  125.        dwError = GetLastError();
  126.        panic();
  127.    }
  128.  
  129.  
  130. #else
  131. #endif
  132.  
  133. /*--------------------------------------------------------------------*/
  134. /*                    Check for special test mode                     */
  135. /*--------------------------------------------------------------------*/
  136.  
  137.    if ( equal(name,"CON"))
  138.    {
  139.       port_active = TRUE;     /* record status for error handler        */
  140.       carrierdetect = FALSE;  /* Modem is not connected                 */
  141.       console = TRUE;
  142.       return 0;
  143.    }
  144.  
  145. /*--------------------------------------------------------------------*/
  146. /*            Reset any errors on the communications port             */
  147. /*--------------------------------------------------------------------*/
  148.  
  149. #ifdef WIN32
  150.    rc = ClearCommError (hCom,
  151.         &Error,
  152.         NULL);
  153.  
  154.    if (!rc) {
  155.       printmsg(0, "openline: Error in ClearCommError() call\n");
  156.       printmsg(0, "Error returned was %ld\n", Error);
  157.    }
  158. #else
  159.    rc = DosDevIOCtl( &com_error, FAR_NULL, ASYNC_GETCOMMERROR ,
  160.                      IOCTL_ASYNC, com_handle);
  161.    if (rc)
  162.    {
  163.       printmsg(0,
  164.             "openline: Unable to read errors for %s, error bits %x",
  165.                name, (int) com_error );
  166.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  167.                (int) rc , (int) rc);
  168.    } /*if */
  169.    else if ( com_error )
  170.       printmsg(0,"openline: Reset errors for %s, error bits were %#04x",
  171.                name, (int) com_error );
  172. #endif
  173. /*--------------------------------------------------------------------*/
  174. /*                           Set baud rate                            */
  175. /*--------------------------------------------------------------------*/
  176.  
  177.    SIOSpeed(baud);
  178.  
  179. /*--------------------------------------------------------------------*/
  180. /*                        Set line attributes                         */
  181. /*--------------------------------------------------------------------*/
  182.  
  183.     printmsg(15,"openline: Getting attributes");
  184.  
  185. #ifdef WIN32
  186.    rc = GetCommState(hCom, &dcb);
  187.    if (!rc) {
  188.       printmsg(0,"openline: Unable to get line attributes for %s",name);
  189.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  190.                (int) rc , (int) rc);
  191.       panic();
  192.    }
  193.  
  194.    dcb.StopBits = ONESTOPBIT;
  195.    dcb.Parity = NOPARITY;
  196.    dcb.ByteSize = 8;
  197.  
  198. #else
  199.    rc = DosDevIOCtl( &com_attrib, FAR_NULL, ASYNC_GETLINECTRL, IOCTL_ASYNC,
  200.                 com_handle);
  201.                               /* Get old attributes from device      */
  202.    if (rc)
  203.    {
  204.       printmsg(0,"openline: Unable to get line attributes for %s",name);
  205.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  206.                (int) rc , (int) rc);
  207.       panic();
  208.    } /*if */
  209.  
  210.    com_attrib.bDataBits = 0x08; /* Use eight bit path for data      */
  211.    com_attrib.bParity   = 0x00; /* No parity                        */
  212.    com_attrib.bStopBits = 0x00; /* 1 Stop Bit                       */
  213. #endif
  214.  
  215.    printmsg(15,"openline: Setting attributes");
  216.  
  217. #ifdef WIN32
  218.    rc = SetCommState(hCom, &dcb);
  219.    if (!rc)
  220.    {
  221.       printmsg(0,"openline: Unable to set line attributes for %s",name);
  222.       panic();
  223.    }
  224. #else
  225.    rc = DosDevIOCtl( FAR_NULL, &com_attrib, ASYNC_SETLINECTRL,
  226.                     IOCTL_ASYNC, com_handle);
  227.    if (rc)
  228.    {
  229.       printmsg(0,"openline: Unable to set line attributes for %s",name);
  230.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  231.                (int) rc , (int) rc);
  232.       panic();
  233.    } /*if */
  234. #endif
  235.  
  236. /*--------------------------------------------------------------------*/
  237. /*                        Disable flow control                        */
  238. /*--------------------------------------------------------------------*/
  239.  
  240.    printmsg(15,"openline: Getting flow control information");
  241. #ifdef WIN32
  242.    GetCommState(hCom, &dcb);
  243.    dcb.fOutX = 0;
  244.    dcb.fInX = 0;
  245.    rc = SetCommState(hCom, &dcb);
  246.    if (!rc) {
  247.        printmsg(0,"openline: Unable to get line attributes for %s",name);
  248.        panic();
  249.    }
  250. #else
  251.    rc = DosDevIOCtl( &com_dcbinfo, FAR_NULL, ASYNC_GETDCBINFO, IOCTL_ASYNC,
  252.                  com_handle);
  253.                               /* Get old attributes from device      */
  254.    if (rc)
  255.    {
  256.       printmsg(0,"openline: Unable to get line attributes for %s",name);
  257.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  258.                (int) rc , (int) rc);
  259.       panic();
  260.    } /*if */
  261.  
  262.    com_dcbinfo.usWriteTimeout = 2999;  /* Write timeout 30 seconds   */
  263.    com_dcbinfo.usReadTimeout = 24;     /* Read timeout .25 seconds   */
  264.    com_dcbinfo.fbCtlHndShake = 0;      /* No control/handshake by OS */
  265.    com_dcbinfo.fbFlowReplace = 0;      /* No flow control, either    */
  266.    com_dcbinfo.fbTimeout = MODE_READ_TIMEOUT | MODE_NO_WRITE_TIMEOUT;
  267. #endif
  268.    printmsg(15,"openline: Setting dcb information");
  269. #ifdef WIN32
  270. #else
  271.    rc = DosDevIOCtl( FAR_NULL, &com_dcbinfo, ASYNC_SETDCBINFO,
  272.                      IOCTL_ASYNC, com_handle);
  273.    if ( rc )
  274.    {
  275.       printmsg(0,"openline: Unable to set flow control for %s",name);
  276.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  277.                (int) rc , (int) rc);
  278.       panic();
  279.    } /*if */
  280. #endif
  281. /*--------------------------------------------------------------------*/
  282. /*                     Raise Data Terminal Ready                      */
  283. /*--------------------------------------------------------------------*/
  284.  
  285. #ifdef WIN32
  286.    GetCommState(hCom, &dcb);
  287.    dcb.fDtrControl = DTR_CONTROL_ENABLE;
  288.    dcb.fRtsControl = RTS_CONTROL_ENABLE;
  289.  
  290.    rc = SetCommState(hCom, &dcb);
  291.    if (!rc) {
  292.       printmsg(0,
  293.             "openline: Unable to raise DTR/RTS for %s",
  294.                   name);
  295.       panic();
  296.    }
  297.  
  298. #else
  299.    com_signals.fbModemOn = DTR_ON | RTS_ON;
  300.    com_signals.fbModemOff = 0xff;
  301. #endif
  302.  
  303.  
  304.    printmsg(15,"openline: Raising RTS/DTR");
  305.  
  306. #ifdef WIN32
  307. #else
  308.    rc = DosDevIOCtl( &com_error, &com_signals, ASYNC_SETMODEMCTRL,
  309.                      IOCTL_ASYNC, com_handle);
  310.    if (rc)
  311.    {
  312.       printmsg(0,
  313.             "openline: Unable to raise DTR/RTS for %s, error bits %#x",
  314.                   name, (int) com_error );
  315.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  316.                (int) rc , (int) rc);
  317.       panic();
  318.    } /*if */
  319. #endif
  320. /*--------------------------------------------------------------------*/
  321. /*        Log serial line data only if log file already exists        */
  322. /*--------------------------------------------------------------------*/
  323.  
  324.    log_handle = open(LINELOG, O_WRONLY | O_TRUNC | O_BINARY);
  325.    if (log_handle != -1) {
  326.       printmsg(15, "openline: logging serial line data to %s", LINELOG);
  327.       log_stream = fdopen(log_handle, "wb");
  328.    }
  329.  
  330.    port_active = TRUE;     /* record status for error handler */
  331.  
  332. /*--------------------------------------------------------------------*/
  333. /*                     Up our processing priority                     */
  334. /*--------------------------------------------------------------------*/
  335.  
  336. #ifdef WIN32
  337.    hProcess = GetCurrentProcess();
  338.    rc = SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS);
  339.  
  340.    if (!rc)
  341.    {
  342.       printmsg(0, "openline: unable to set priority for process");
  343.       panic();
  344.    }
  345. #else
  346.    rc = DosGetPrty(PRTYS_PROCESS, &usPrevPriority, 0);
  347.    if (rc)
  348.    {
  349.       printmsg(0,"openline: Unable to get priority for task");
  350.       printmsg(0,"Return code from DosGetPrty was %#04x (%d)",
  351.                (int) rc , (int) rc);
  352.       panic();
  353.    } /*if */
  354.  
  355.    rc = DosSetPrty(PRTYS_PROCESS, PRTYC_TIMECRITICAL, 0, 0);
  356.    if (rc)
  357.    {
  358.       printmsg(0,"openline: Unable to set priority for task");
  359.       printmsg(0,"Return code from DosSetPrty was %#04x (%d)",
  360.                (int) rc , (int) rc);
  361.    } /*if */
  362. #endif
  363. /*--------------------------------------------------------------------*/
  364. /*                     Wait for port to stablize                      */
  365. /*--------------------------------------------------------------------*/
  366.  
  367.    ddelay(500);            /* Allow port to stablize          */
  368.    return 0;
  369.  
  370. } /*openline*/
  371.  
  372.  
  373. /*--------------------------------------------------------------------*/
  374. /*    s r e a d                                                       */
  375. /*                                                                    */
  376. /*    Read from the serial port                                       */
  377. /*                                                                    */
  378. /*   Non-blocking read essential to "g" protocol.  See "dcpgpkt.c"    */
  379. /*   for description.                                                 */
  380. /*                                                                    */
  381. /*   This all changes in a multi-tasking system.  Requests for I/O    */
  382. /*   should get queued and an event flag given.  Then the             */
  383. /*   requesting process (e.g. gmachine()) waits for the event flag    */
  384. /*   to fire processing either a read or a write.  Could be           */
  385. /*   implemented on VAX/VMS or DG but not MS-DOS.                     */
  386. /*--------------------------------------------------------------------*/
  387.  
  388. unsigned int sread(char *output, unsigned int wanted, unsigned int timeout)
  389. {
  390. #ifdef WIN32
  391.    static LPVOID psave;
  392.    DWORD Error;
  393. #endif
  394.    static char save[BUFSIZ];
  395.    static USHORT bufsize = 0;
  396.    USHORT rc;
  397.    time_t stop_time ;
  398.    time_t now ;
  399.  
  400. /*--------------------------------------------------------------------*/
  401. /*           Determine if our internal buffer has the data            */
  402. /*--------------------------------------------------------------------*/
  403.  
  404.    if (bufsize >= wanted)
  405.    {
  406.       memmove( output, save, wanted );
  407.       bufsize -= wanted;
  408.       if ( bufsize )          /* Any data left over?                 */
  409.          memmove( save, &save[wanted], bufsize );  /* Yes --> Save it*/
  410.  
  411.       return wanted + bufsize;
  412.    } /* if */
  413.  
  414. /*--------------------------------------------------------------------*/
  415. /*            Reset any errors on the communications port             */
  416. /*--------------------------------------------------------------------*/
  417.  
  418. #ifdef WIN32
  419.    printmsg(3, "sread: Calling ClearCommError\n");
  420.    rc = ClearCommError (hCom,
  421.         &Error,
  422.         NULL);
  423.  
  424.    if (!rc) {
  425.       printmsg(0, "sread:  Unable to read port errors\n");
  426.       printmsg(0, "Error mask was set to %ld\n", Error);
  427.    }
  428.  
  429. #else
  430.  
  431.    rc = DosDevIOCtl( &com_error, FAR_NULL, ASYNC_GETCOMMERROR ,
  432.                      IOCTL_ASYNC, com_handle);
  433.    if (rc)
  434.    {
  435.       printmsg(0,"sread: Unable to read port errors");
  436.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  437.                (int) rc , (int) rc);
  438.    } /*if */
  439.    else if ( com_error )
  440.       printmsg(0,"sread: Reset port error, error bits were %#04x",
  441.                (int) com_error );
  442. #endif
  443.  
  444. /*--------------------------------------------------------------------*/
  445. /*                 Determine when to stop processing                  */
  446. /*--------------------------------------------------------------------*/
  447.  
  448.    if ( timeout == 0 )
  449.    {
  450.       stop_time = 0;
  451.       now = 1;                /* Any number greater than stop time   */
  452.    }
  453.    else {
  454.       time( & now );
  455.       stop_time = now + timeout;
  456.    }
  457.  
  458. /*--------------------------------------------------------------------*/
  459. /*            Try to read any needed data into the buffer             */
  460. /*--------------------------------------------------------------------*/
  461.  
  462.    do {
  463.  
  464.       
  465. #ifdef WIN32
  466.       DWORD received;
  467.       DWORD needed = wanted - bufsize;
  468.       COMMTIMEOUTS CommTimeout;
  469.       DWORD port_timeout;
  470. #else
  471.       USHORT needed =  (USHORT) wanted - bufsize;
  472.       USHORT port_timeout;
  473.       USHORT received = 0;
  474. #endif
  475. /*--------------------------------------------------------------------*/
  476. /*           Compute a new timeout for the read, if needed            */
  477. /*--------------------------------------------------------------------*/
  478.  
  479.  
  480.       if (stop_time > now )
  481.       {
  482.          port_timeout = (USHORT) (stop_time - now) / needed * 100;
  483.          if (port_timeout < 100)
  484.             port_timeout = 100;
  485.       }
  486.       else if (! console) 
  487. #ifdef WIN32
  488.       {
  489.           port_timeout = 0xffffffff;
  490.           CommTimeout.ReadTotalTimeoutConstant = 0;
  491.           CommTimeout.WriteTotalTimeoutConstant = 0;
  492.           CommTimeout.ReadIntervalTimeout = port_timeout;
  493.           CommTimeout.ReadTotalTimeoutMultiplier = 1;
  494.           CommTimeout.WriteTotalTimeoutMultiplier = 1;
  495.           SetCommTimeouts(hCom, &CommTimeout);
  496.       }
  497. #else
  498.          port_timeout = 0;
  499. #endif
  500.  
  501.  
  502.  
  503. #ifdef WIN32
  504.  
  505.        if ( port_timeout != CommTimeout.ReadIntervalTimeout ) {
  506.  
  507.           CommTimeout.ReadTotalTimeoutConstant = port_timeout;
  508.           CommTimeout.WriteTotalTimeoutConstant = port_timeout;
  509.           CommTimeout.ReadIntervalTimeout = port_timeout;
  510.           CommTimeout.ReadTotalTimeoutMultiplier = 1;
  511.           CommTimeout.WriteTotalTimeoutMultiplier = 1;
  512.           rc = SetCommTimeouts(hCom, &CommTimeout);
  513.  
  514.           if (!rc) {
  515.  
  516.             rc = SetCommTimeouts(hCom, &CommTimeout);
  517.              /*
  518.              printmsg(0,"sread: Unable to set timeout for comm port");
  519.              */
  520.              /* panic(); */
  521.           }
  522.         }
  523. #else
  524.       if ( port_timeout != com_dcbinfo.usReadTimeout ){
  525.          com_dcbinfo.usReadTimeout = port_timeout;
  526.          rc = DosDevIOCtl(FAR_NULL, &com_dcbinfo, ASYNC_SETDCBINFO,
  527.                           IOCTL_ASYNC, com_handle);
  528.          if ( rc )
  529.          {
  530.             printmsg(0,"sread: Unable to set timeout for comm port");
  531.             printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  532.                      (int) rc , (int) rc);
  533.             panic();
  534.          } /*if */
  535.          printmsg(15,"sread: new port time out is %d seconds/100",
  536.                   port_timeout);
  537.       } /* if */
  538.  
  539. #endif
  540. /*--------------------------------------------------------------------*/
  541. /*                 Read the data from the serial port                 */
  542. /*--------------------------------------------------------------------*/
  543.  
  544. #ifdef WIN32
  545.  
  546.       rc = ReadFile (hCom, &save[bufsize], needed, &received, NULL);
  547.  
  548.       if (!rc) {
  549.          printmsg(0,"sread: Read from comm port for %d bytes failed, received = %d.",
  550.             needed,received);
  551.          bufsize = 0;
  552.          return 0;
  553.       }
  554. #else
  555.       rc = DosRead( com_handle, &save[bufsize], needed, &received );
  556.  
  557.       if ( rc != 0 )
  558.       {
  559.          printmsg(0,"sread: Read from comm port for %d bytes failed.",
  560.                   needed);
  561.          printmsg(0,"Return code from DosRead was %#04x (%d)",
  562.                   (int) rc , (int) rc);
  563.          bufsize = 0;
  564.          return 0;
  565.       }
  566. #endif
  567.       printmsg(15,"sread: Want %d characters, received %d, total %d in buffer",
  568.             (int) wanted, (int) received, (int) bufsize + received);
  569.  
  570. /*--------------------------------------------------------------------*/
  571. /*                    Log the newly received data                     */
  572. /*--------------------------------------------------------------------*/
  573.  
  574.       if (log_handle != -1)
  575.       {
  576. #ifdef VERBOSE
  577.          size_t column;
  578. #endif
  579.          if (logmode != READING)
  580.          {
  581.             fputs("\nRead:  ", log_stream);
  582.             logmode = READING;
  583.          } /* if */
  584. #ifdef VERBOSE
  585.          for (column = 0; column < received; column++) {
  586.             char s[18];
  587.             itoa(0x100 | (unsigned) save[bufsize + column], s, 16);
  588.                                           /* Make it printable hex   */
  589.             fwrite(s, 1, 2, log_stream);  /* Write hex to the log    */
  590.          } /* for */
  591. #else
  592.          fwrite(&save[bufsize], 1, received, log_stream);
  593. #endif
  594.       } /* if */
  595.  
  596. /*--------------------------------------------------------------------*/
  597. /*            If we got the data, return it to the caller             */
  598. /*--------------------------------------------------------------------*/
  599.  
  600.       bufsize += received;
  601.       if ( bufsize == wanted )
  602.  
  603.       {
  604.          memmove( output, save, bufsize);
  605.          bufsize = 0;
  606.  
  607.          if (debuglevel > 14)
  608.             fwrite(output,1,bufsize,stdout);
  609.  
  610.          return wanted;
  611.       } /* if */
  612.  
  613. /*--------------------------------------------------------------------*/
  614. /*                 Update the clock for the next pass                 */
  615. /*--------------------------------------------------------------------*/
  616.  
  617.       if (stop_time > 0)
  618.          time( &now );
  619.  
  620.    } while (stop_time > now);
  621.  
  622. /*--------------------------------------------------------------------*/
  623. /*         We don't have enough data; report what we do have          */
  624. /*--------------------------------------------------------------------*/
  625.  
  626.    return bufsize;
  627.  
  628. } /*sread*/
  629.  
  630.  
  631. /*--------------------------------------------------------------------*/
  632. /*    s w r i t e                                                     */
  633. /*                                                                    */
  634. /*    Write to the serial port                                        */
  635. /*--------------------------------------------------------------------*/
  636.  
  637. int swrite(char *data, unsigned int len)
  638. {
  639. #ifdef WIN32
  640.    DWORD bytes;
  641.    BOOL rc;
  642. #else
  643.    size_t bytes;
  644.    USHORT rc;
  645. #endif
  646.    hangup_needed = TRUE;      /* Flag that the port is now dirty  */
  647.  
  648. /*--------------------------------------------------------------------*/
  649. /*         Write the data out as the queue becomes available          */
  650. /*--------------------------------------------------------------------*/
  651.  
  652. #ifdef WIN32
  653.    rc = WriteFile (hCom, data, len, &bytes, NULL);
  654.  
  655.    if (!rc) {
  656.       printmsg(0,"swrite: Write to communications port failed.");
  657.       return bytes;
  658.    }
  659. #else
  660.    rc = DosWrite( com_handle, data , len, &bytes);
  661.    if (rc)
  662.    {
  663.       printmsg(0,"swrite: Write to communications port failed.");
  664.       printmsg(0,"Return code from DosWrite was %#04x (%d)",
  665.                (int) rc , (int) rc);
  666.       return bytes;
  667.    } /*if */
  668. #endif
  669.  
  670. /*--------------------------------------------------------------------*/
  671. /*                        Log the data written                        */
  672. /*--------------------------------------------------------------------*/
  673.  
  674.    if (log_handle != -1) {
  675. #ifdef VERBOSE
  676.       char s[18];
  677. #endif
  678.       if (logmode != WRITING)
  679.       {
  680.          fputs("\nWrite: ", log_stream);
  681.          logmode = WRITING;
  682.       }
  683. #ifdef VERBOSE
  684.       for (bytes = 0; bytes < len; bytes++) {
  685.          itoa(0x100 | (unsigned) *data++, s, 16);
  686.                                         /* Make it printable hex  ahd */
  687.          fputc(s[1], log_stream);       /* Put it in the log    */
  688.          fputc(s[2], log_stream);       /* Put it in the log    */
  689.       }
  690. #else
  691.       fwrite(data, 1, len, log_stream);
  692. #endif
  693.    }
  694.  
  695. /*--------------------------------------------------------------------*/
  696. /*            Return bytes written to the port to the caller          */
  697. /*--------------------------------------------------------------------*/
  698.  
  699.    return len;
  700.  
  701. } /*swrite*/
  702.  
  703.  
  704. /*--------------------------------------------------------------------*/
  705. /*    s s e n d b r k                                                 */
  706. /*                                                                    */
  707. /*    send a break signal out the serial port                         */
  708. /*--------------------------------------------------------------------*/
  709.  
  710. void ssendbrk(unsigned int duration)
  711. {
  712.  
  713.    printmsg(12, "ssendbrk: %d", duration);
  714.  
  715. #ifdef WIN32
  716.    SetCommBreak(hCom);
  717. #else
  718.    DosDevIOCtl( &com_error, FAR_NULL, ASYNC_SETBREAKON, IOCTL_ASYNC,
  719.                 com_handle);
  720. #endif
  721.    ddelay( duration == 0 ? 200 : duration);
  722.  
  723. #ifdef WIN32
  724.    ClearCommBreak(hCom);
  725. #else
  726.    DosDevIOCtl( &com_error, FAR_NULL, ASYNC_SETBREAKOFF, IOCTL_ASYNC,
  727.                 com_handle);
  728. #endif
  729. } /*ssendbrk*/
  730.  
  731.  
  732. /*--------------------------------------------------------------------*/
  733. /*    c l o s e l i n e                                               */
  734. /*                                                                    */
  735. /*    Close the serial port down                                      */
  736. /*--------------------------------------------------------------------*/
  737.  
  738. void closeline(void)
  739. {
  740.    USHORT rc;
  741.    HANDLE hProcess;
  742.  
  743.    if ( ! port_active )
  744.       panic();
  745.  
  746.    port_active = FALSE; /* flag port closed for error handler  */
  747.    hangup_needed = FALSE;  /* Don't fiddle with port any more  */
  748.  
  749. /*--------------------------------------------------------------------*/
  750. /*                           Lower priority                           */
  751. /*--------------------------------------------------------------------*/
  752.  
  753. #ifdef WIN32
  754.    hProcess = GetCurrentProcess();
  755.    rc = SetPriorityClass(hProcess, NORMAL_PRIORITY_CLASS);
  756.  
  757.    if (!rc)
  758.    {
  759.       printmsg(0, "closeline:  Unable to lower priority for task");
  760.       panic();
  761.    }
  762. #else
  763.    rc = DosSetPrty(PRTYS_PROCESS,
  764.                    usPrevPriority >> 8 ,
  765.                    usPrevPriority & 0xff, 0);
  766.    if (rc)
  767.    {
  768.       printmsg(0,"closeline: Unable to set priority for task");
  769.       printmsg(0,"Return code from DosSetPrty was %#04x (%d)",
  770.                (int) rc , (int) rc);
  771.    } /*if */
  772. #endif
  773. /*--------------------------------------------------------------------*/
  774. /*                             Lower DTR                              */
  775. /*--------------------------------------------------------------------*/
  776.  
  777. #ifdef WIN32
  778.    if (!EscapeCommFunction(hCom, CLRDTR | CLRRTS))
  779.    {
  780.       printmsg(0,"closeline: Unable to lower DTR/RTS");
  781.    }
  782.  
  783. #else
  784.    com_signals.fbModemOn  = 0x00;
  785.    com_signals.fbModemOff = DTR_OFF | RTS_OFF;
  786.  
  787.  
  788.    if (DosDevIOCtl( &com_error, &com_signals, ASYNC_SETMODEMCTRL,
  789.                     IOCTL_ASYNC, com_handle))
  790.    {
  791.       printmsg(0,"closeline: Unable to lower DTR/RTS for %s",name);
  792.    } /*if */
  793.  
  794. #endif
  795. /*--------------------------------------------------------------------*/
  796. /*                      Actually close the port                       */
  797. /*--------------------------------------------------------------------*/
  798.  
  799. #ifdef WIN32
  800.    if(!CloseHandle(hCom))
  801.    {
  802.       printmsg(0, "closeline: close of serial port failed");
  803.    }
  804. #else
  805.    rc = DosClose( com_handle );
  806.  
  807.    if (rc != 0)
  808.       printmsg(0, "closeline: close of serial port failed, reason %d", (int) rc);
  809. #endif
  810.  
  811. /*--------------------------------------------------------------------*/
  812. /*                   Stop logging the data to disk                    */
  813. /*--------------------------------------------------------------------*/
  814.  
  815.    if (log_handle != -1) {    /* close serial line log file */
  816.       fclose(log_stream);
  817.       close(log_handle);
  818.    };
  819.  
  820.    printmsg(3,"Serial port closed");
  821.  
  822. } /*closeline*/
  823.  
  824.  
  825. /*--------------------------------------------------------------------*/
  826. /*    H a n g u p                                                     */
  827. /*                                                                    */
  828. /*    Hangup the telephone by dropping DTR.  Works with HAYES and     */
  829. /*    many compatibles.                                               */
  830. /*    14 May 89 Drew Derbyshire                                       */
  831. /*--------------------------------------------------------------------*/
  832.  
  833. void hangup( void )
  834. {
  835.    if (!hangup_needed || console)
  836.       return;
  837.    hangup_needed = FALSE;
  838.  
  839. /*--------------------------------------------------------------------*/
  840. /*                              Drop DTR                              */
  841. /*--------------------------------------------------------------------*/
  842.  
  843. #ifdef WIN32
  844.    if (!EscapeCommFunction(hCom, CLRDTR))
  845.    {
  846.       printmsg(0, "hangup: Unable to lower DTR for comm port");
  847.       panic();
  848.    }
  849. #else
  850.    com_signals.fbModemOn  = 0x00;
  851.    com_signals.fbModemOff = DTR_OFF;
  852.  
  853.    if (DosDevIOCtl( &com_error, &com_signals, ASYNC_SETMODEMCTRL,
  854.                      IOCTL_ASYNC, com_handle))
  855.    {
  856.       printmsg(0,"hangup: Unable to lower DTR for comm port");
  857.       panic();
  858.    } /*if */
  859. #endif
  860. /*--------------------------------------------------------------------*/
  861. /*                  Wait for the telephone to hangup                  */
  862. /*--------------------------------------------------------------------*/
  863.  
  864.    printmsg(3,"hangup: Dropped DTR");
  865.    ddelay(500);            /* Really only need 250 milliseconds         */
  866.  
  867.  
  868. /*--------------------------------------------------------------------*/
  869. /*                          Bring DTR backup                          */
  870. /*--------------------------------------------------------------------*/
  871.  
  872. #ifdef WIN32
  873.    if (!EscapeCommFunction(hCom, SETDTR))
  874.    {
  875.       printmsg(0, "hangup: Unable to raise DTR for comm port");
  876.       panic();
  877.    }
  878. #else
  879.    com_signals.fbModemOn = DTR_ON;
  880.    com_signals.fbModemOff = 0xff;
  881.  
  882.    if (DosDevIOCtl( &com_error, &com_signals, ASYNC_SETMODEMCTRL,
  883.                      IOCTL_ASYNC, com_handle))
  884.    {
  885.       printmsg(0,"hangup: Unable to raise DTR for comm port");
  886.       panic();
  887.    } /*if */
  888.  
  889. #endif
  890.    ddelay(500);            /* Now wait for the poor thing to recover    */
  891.  
  892. }
  893.  
  894.  
  895. /*--------------------------------------------------------------------*/
  896. /* S I O S p e e d                                                    */
  897. /*                                                                    */
  898. /* Re-specify the speed of an opened serial port                      */
  899. /*                                                                    */
  900. /* Dropped the DTR off/on calls because this makes a Hayes drop the   */
  901. /* line if configured properly, and we don't want the modem to drop   */
  902. /* the phone on the floor if we are performing autobaud.              */
  903. /*                                                                    */
  904. /* (Configured properly = standard method of making a Hayes hang up   */
  905. /* the telephone, especially when you can't get it into command state */
  906. /* because it is at the wrong speed or whatever.)                     */
  907. /*--------------------------------------------------------------------*/
  908.  
  909. void SIOSpeed(BPS baud)
  910. {
  911.    USHORT rc;
  912.  
  913.    printmsg(15,"SIOSpeed: Setting baud rate to %d", (int) baud);
  914. #ifdef WIN32
  915.  
  916.    GetCommState (hCom, &dcb);
  917.    dcb.BaudRate = baud;
  918.    rc = SetCommState (hCom, &dcb);
  919.    if (!rc && !console) {
  920.       printmsg(0,"SIOSPeed: Unable to set baud rate for port to %d",baud);
  921.       panic();
  922.    }
  923.  
  924. #else
  925.    rc = DosDevIOCtl( FAR_NULL, &baud,
  926.                      ASYNC_SETBAUDRATE, IOCTL_ASYNC, com_handle);
  927.    if (rc)
  928.    {
  929.       printmsg(0,"SIOSPeed: Unable to set baud rate for port to %d",
  930.                baud);
  931.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  932.                (int) rc , (int) rc);
  933.       panic();
  934.    } /*if */
  935. #endif
  936.    current_baud = baud;
  937.  
  938. } /*SIOSpeed*/
  939.  
  940. /*--------------------------------------------------------------------*/
  941. /*    f l o w c o n t r o l                                           */
  942. /*                                                                    */
  943. /*    Enable/Disable in band (XON/XOFF) flow control                  */
  944. /*--------------------------------------------------------------------*/
  945.  
  946.  
  947. void flowcontrol( boolean flow )
  948. {
  949.    USHORT rc;
  950. #ifdef WIN32
  951.    DCB dcb;
  952.  
  953.    if (console)
  954.       return;
  955.  
  956.    GetCommState(hCom, &dcb);
  957.  
  958.    if (flow)
  959.    {
  960.       dcb.fOutX = TRUE;
  961.       dcb.fInX = TRUE;
  962.       dcb.fRtsControl = RTS_CONTROL_ENABLE;
  963.       dcb.fOutxCtsFlow = FALSE;
  964.       rc = SetCommState(hCom, &dcb);
  965.    } else {
  966.       dcb.fOutX = FALSE;
  967.       dcb.fInX = FALSE;
  968.       dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
  969.       dcb.fOutxCtsFlow = TRUE;
  970.       rc = SetCommState(hCom, &dcb);
  971.    }
  972.  
  973.    if ( rc )
  974.    {
  975.       printmsg(0,"flowcontrol: Unable to set flow control");
  976.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  977.                (int) rc , (int) rc);
  978.       panic();
  979.    } /*if */
  980. #else
  981.    if ( flow )
  982.        com_dcbinfo.fbFlowReplace = (char)
  983.             (com_dcbinfo.fbFlowReplace |
  984.             (MODE_AUTO_TRANSMIT | MODE_AUTO_RECEIVE));
  985.    else
  986.       com_dcbinfo.fbFlowReplace = (char)
  987.             (com_dcbinfo.fbFlowReplace &
  988.             (0xff - MODE_AUTO_TRANSMIT - MODE_AUTO_RECEIVE));
  989.  
  990.    rc = DosDevIOCtl( FAR_NULL, &com_dcbinfo, ASYNC_SETDCBINFO,
  991.                      IOCTL_ASYNC, com_handle);
  992.  
  993.    if ( rc )
  994.    {
  995.       printmsg(0,"flowcontrol: Unable to set flow control for %s",name);
  996.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  997.                (int) rc , (int) rc);
  998.       panic();
  999.    } /*if */
  1000. #endif
  1001. } /*flowcontrol*/
  1002.  
  1003. /*--------------------------------------------------------------------*/
  1004. /*    G e t S p e e d                                                 */
  1005. /*                                                                    */
  1006. /*    Report current speed of communications connection               */
  1007. /*--------------------------------------------------------------------*/
  1008.  
  1009. BPS GetSpeed( void )
  1010. {
  1011.    return current_baud;
  1012. } /* GetSpeed */
  1013.  
  1014. /*--------------------------------------------------------------------*/
  1015. /*   C D                                                              */
  1016. /*                                                                    */
  1017. /*   Return status of carrier detect                                  */
  1018. /*--------------------------------------------------------------------*/
  1019.  
  1020. boolean CD( void )
  1021. {
  1022.     DWORD dwModemStatus;
  1023.  
  1024.    boolean online = carrierdetect;
  1025.    BYTE status;
  1026.    USHORT rc;
  1027.  
  1028.    if ( console )
  1029.       return feof( stdin ) == 0;
  1030.  
  1031.    rc = GetCommModemStatus(hCom, &dwModemStatus);
  1032.    if ( rc )
  1033.    {
  1034.       printmsg(0,"CD: Unable to get modem status");
  1035.       printmsg(0,"Return code from GetCommModemStatus() was %#04x (%d)",
  1036.                (int) rc , (int) rc);
  1037.       panic();
  1038.    } /*if */
  1039.  
  1040. /*--------------------------------------------------------------------*/
  1041. /*    If we previously had carrier detect but have lost it, we        */
  1042. /*    report it was lost.  If we do not yet have carrier detect,      */
  1043. /*    we return success because we may not have connected yet.        */
  1044. /*--------------------------------------------------------------------*/
  1045.  
  1046.    carrierdetect = dwModemStatus && MS_RLSD_ON;
  1047.  
  1048.    if (online)
  1049.       return (status && (MS_RLSD_ON || MS_DSR_ON));
  1050.    else
  1051.       return (status && MS_DSR_ON);
  1052.  
  1053. } /* CD */
  1054.  
  1055. void setstdinmode(void)
  1056. {
  1057.    HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
  1058.    DWORD mode;
  1059.    BOOL bSuccess;
  1060.  
  1061.    bSuccess = GetConsoleMode(hStdIn, &mode);
  1062.  
  1063. /* Disable mouse events so that later Peeks() only get characters */
  1064.    mode &= ~ENABLE_WINDOW_INPUT;
  1065.    mode &= ~ENABLE_MOUSE_INPUT;
  1066.    mode &= ~ENABLE_LINE_INPUT;
  1067.    mode |= ENABLE_PROCESSED_INPUT;
  1068.  
  1069.    SetConsoleMode(hStdIn, mode);
  1070. }